﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Dingding.Helper.Redis
{
    public class StackExchange_RedisV1 : IDisposable
    {
        //readonly‌确保字段只能在声明时或构造函数中初始化，之后不可修改（运行时常量）

        private readonly ConnectionMultiplexer _redisConnection; 

        private readonly IDatabase _cache; 


        public StackExchange_RedisV1(string connectionString)
        {
            if (string.IsNullOrWhiteSpace(connectionString))
                throw new ArgumentException("Redis connection string cannot be null or empty.", nameof(connectionString));

            // 初始化 Redis 连接
            _redisConnection = ConnectionMultiplexer.Connect(connectionString);
            _cache = _redisConnection.GetDatabase();
        }

        #region 单记录操作

        // 同步：设置键值对
        public bool SetValue(string key, string value, TimeSpan? expiry = null)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return _cache.StringSet(key, value, expiry);
        }



        // 同步：获取值
        public string GetValue(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return _cache.StringGet(key);
        }


        // 异步：设置键值对
        public async Task<bool> SetValueAsync(string key, string value, TimeSpan? expiry = null)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return await _cache.StringSetAsync(key, value, expiry);
        }


        // 异步：获取值
        public async Task<string> GetValueAsync(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return await _cache.StringGetAsync(key);
        }

        #endregion






        #region 多记录操作

        // 同步：批量设置键值对
        public bool SetValues(Dictionary<string, string> values, TimeSpan? expiry = null)
        {
            if (values == null || !values.Any()) throw new ArgumentException("Values cannot be null or empty.", nameof(values));

            var entries = values.Select(kv => new KeyValuePair<RedisKey, RedisValue>(kv.Key, kv.Value)).ToArray();
            foreach (var entry in entries)
                _cache.StringSet(entry.Key, entry.Value, expiry);

            return true; // Assume success for simplicity
        }

       

        // 同步：批量获取值
        public Dictionary<string, string> GetValues(IEnumerable<string> keys)
        {
            if (keys == null || !keys.Any()) throw new ArgumentException("Keys cannot be null or empty.", nameof(keys));

            var redisKeys = keys.Select(k => (RedisKey)k).ToArray();
            var redisValues = _cache.StringGet(redisKeys);

            return redisKeys.Zip(redisValues,
                (key, value) => new KeyValuePair<string, string>(key.ToString(), value)).ToDictionary(kv => kv.Key, kv => kv.Value);
        }

        // 异步：批量设置键值对
        public async Task<bool> SetValuesAsync(Dictionary<string, string> values, TimeSpan? expiry = null)
        {
            if (values == null || !values.Any()) throw new ArgumentException("Values cannot be null or empty.", nameof(values));

            var tasks = values.Select(kv => _cache.StringSetAsync(kv.Key, kv.Value, expiry)).ToArray();
            await Task.WhenAll(tasks);

            return true; // Assume success for simplicity
        }

        // 异步：批量获取值
        public async Task<Dictionary<string, string>> GetValuesAsync(IEnumerable<string> keys)
        {
            if (keys == null || !keys.Any()) throw new ArgumentException("Keys cannot be null or empty.", nameof(keys));

            var redisKeys = keys.Select(k => (RedisKey)k).ToArray();
            var redisValues = await _cache.StringGetAsync(redisKeys);

            return redisKeys.Zip(redisValues,
                (key, value) => new KeyValuePair<string, string>(key.ToString(), value)).ToDictionary(kv => kv.Key, kv => kv.Value);
        }

        #endregion



        #region 其他操作

        // 检查键是否存在（同步）
        public bool KeyExists(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return _cache.KeyExists(key);
        }

        // 检查键是否存在（异步）
        public async Task<bool> KeyExistsAsync(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return await _cache.KeyExistsAsync(key);
        }

        // 删除键（同步）
        public bool DeleteKey(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return _cache.KeyDelete(key);
        }

        // 删除键（异步）
        public async Task<bool> DeleteKeyAsync(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Key cannot be null or empty.", nameof(key));
            return await _cache.KeyDeleteAsync(key);
        }

        #endregion

        #region 资源释放

        public void Dispose()
        {
            if (_redisConnection != null && _redisConnection.IsConnected)
            {
                _redisConnection.Dispose();
            }
        }

        #endregion
    }
}